package com.lcx.plugin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.lcx.plugin.dto.ColumnIndexDTO;
import com.lcx.plugin.dto.ExcelDbFiledDTO;
import com.lcx.plugin.dto.MySettingsStorageDTO;
import com.lcx.plugin.factory.SqlHandleFactory;
import com.lcx.plugin.handle.JdbcHandle;
import com.lcx.plugin.service.ExcelAnalysisService;
import com.lcx.plugin.service.MySettingsStorageService;
import com.lcx.plugin.service.SqlHandleService;
import com.lcx.plugin.tool.CacheDataUtils;
import com.lcx.plugin.tool.ComponentUtil;

import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author daxiong
 * @date 2023/6/14 下午2:29
 */
public class ExcelAnalysisServiceImpl extends AnalysisEventListener<Map<Integer, Object>> implements ExcelAnalysisService {

    private int rowNumber;
    private String tableName;
    private String tableNote;
    List<Map<String, Object>> list = new ArrayList<>();
    /**
     * 数据缓存工具类
     */
    private final CacheDataUtils cacheDataUtils = CacheDataUtils.getInstance();
    /**
     * 用户的自定义配置
     * field:0
     */
    Map<String, Integer> finalMatchMap;

    private String finalSqlStr = "";

    public ExcelAnalysisServiceImpl() {
        MySettingsStorageDTO settingsStorage = MySettingsStorageService.getSettingsStorage();
        ColumnIndexDTO columnIndexDTO = settingsStorage.getColumnIndexDTO();
        // 用户的自定义配置map
        finalMatchMap = JSONUtil.toBean(JSONUtil.parseObj(columnIndexDTO), Map.class);
    }

    @Override
    public void runSql() {
        if (cacheDataUtils.isSql2Clipboard()) {
            StringSelection selection = new StringSelection(finalSqlStr);
            Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
            clipboard.setContents(selection, selection);
            ComponentUtil.showNotification(cacheDataUtils.getProject(), "成功生成sql语句, 已经复制到剪贴板！", true);
        } else {
            JdbcHandle jdbcHandle = new JdbcHandle(cacheDataUtils.getDbConfig());
            jdbcHandle.executeSql(finalSqlStr);
        }
    }

    @Override
    public void invoke(Map<Integer, Object> data, AnalysisContext context) {
        if (rowNumber < 3) {
            // head头的处理
            if (rowNumber == 0) {
                tableNote = (String) data.get(0);
            }
            if (rowNumber == 1) {
                tableName = (String) data.get(0);
            }
        } else {
            // 将原始数据 0:id 转换为 field:id
            Map<String, Object> result = finalMatchMap.entrySet().stream()
                    .collect(HashMap::new, (map, item) -> map.put(item.getKey(), data.get(item.getValue())), HashMap::putAll);
            list.add(result);
        }
        rowNumber++;
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 防止上一个sheet只有表头没有数据
        rowNumber = 0;
        if (CollUtil.isEmpty(list)) {
            // 空的excel sheet
            return;
        }
        // 将map对象转成ExcelDbFiledDTO对象
        List<ExcelDbFiledDTO> objList = transferMap2Object(list);
        // 将对象转成sql执行
        SqlHandleService sqlHandleService = SqlHandleFactory.getSqlHandleServiceByDbType(cacheDataUtils.getDbConfig().getDbType());
        if (Objects.isNull(sqlHandleService)) {
            // 不支持的数据库
            return;
        }
        finalSqlStr += sqlHandleService.generateSql(objList, tableName, tableNote);
        // 执行完一次就清空，重置行索引
        list.clear();
    }


    private List<ExcelDbFiledDTO> transferMap2Object(List<Map<String, Object>> list) {
        return list.stream()
                .map(item -> {
                    ExcelDbFiledDTO excelDbFiledDTO = JSONUtil.toBean(JSONUtil.parseObj(item), ExcelDbFiledDTO.class);
                    excelDbFiledDTO.init();
                    return excelDbFiledDTO;
                })
                .collect(Collectors.toList());
    }

}
